//
//  AppLocationManager.m
//  YYDemo
//
//  Created by lipeng on 2019/4/20.
//  Copyright © 2019 lipeng. All rights reserved.
//

#import "AppLocationManager.h"
#import <CoreLocation/CoreLocation.h>
#import <Contacts/Contacts.h>
#import "Config.h"

@interface AppLocationManager ()<CLLocationManagerDelegate>
{
    dispatch_semaphore_t _lock;
}
@property (nonatomic,strong) CLLocationManager *location;
@property (nonatomic,strong) CLGeocoder *localtionGeocoder;
@end
@implementation AppLocationManager

- (instancetype)init {
    if (self == [super init]) {
        _lock = dispatch_semaphore_create(1);
        _needReverseGeocode = NO;
    }
    return self;
}


#pragma mark - 地理位置
- (CLLocationManager *)setupLocation{
    return self.location;
}

- (CLLocationManager *)location {
    if (_location == nil){
        _location = [[CLLocationManager alloc] init];
        _location.distanceFilter = 100.0;
        _location.desiredAccuracy = kCLLocationAccuracyHundredMeters;
        if (@available(iOS 11.0, *)) {
            _location.showsBackgroundLocationIndicator = YES;
        } else {
            // Fallback on earlier versions
        }
        _location.delegate = self;
    }
    return _location;
}

- (void)stopLocation {
    if (_location) {
        [_location stopUpdatingLocation];
        _location = nil;
    }
}


#pragma mark - 地理编码
- (CLGeocoder *)localtionGeocoder {
    if (_localtionGeocoder == nil) {
        _localtionGeocoder = [[CLGeocoder alloc] init];
    }
    return _localtionGeocoder;
}

#pragma mark - 设置监控范围
- (void)setRegion:(CLRegion *)region {
    LOCK(_lock)
    if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined
        && [CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]){
        NSLog(@"=== startMonitoringForRegion ===");
        if ([CLLocationManager significantLocationChangeMonitoringAvailable]){
            [_location startMonitoringSignificantLocationChanges];
        }
         // 请求一次当前位置
          [_location requestLocation];
          [_location startMonitoringForRegion:region];
    }
    else {
        NSLog(@"== 权限问题 ==");
        [_location stopMonitoringForRegion:region];
    }
    UNLOCK(_lock)
}

#pragma mark - 获取最新位置
- (void)localtionAddress {
    CLLocation *lastLocation = _location.location;
    if (lastLocation) {
        [self.localtionGeocoder reverseGeocodeLocation:lastLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            [placemarks enumerateObjectsUsingBlock:^(CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                [self parsePlaceMark:obj];
            }];
        }];
    }
}

#pragma mark - 解析位置信息

- (void)parsePlaceMark:(CLPlacemark *)placeMark {
    // 地标名称，一般是某个地区地标式建筑/地名等，可能为空；例如：中关村
    NSLog(@"=== placeMark -- name : %@ ===",placeMark.name);
    // 国家编码，例如：CN 中国
    NSLog(@"=== placeMark -- ISOcountryCode: %@ ===",placeMark.ISOcountryCode);
    // 国家名称
    NSLog(@"=== placeMark -- country: %@ ===",placeMark.country);
    // 邮编
    NSLog(@"=== placeMark -- postalCode: %@ ===",placeMark.postalCode);
    // 一个行政区域，一般是省
    NSLog(@"=== placeMark -- administrativeArea: %@ ===",placeMark.administrativeArea);
    // 镇，在直辖市中可能为空
    NSLog(@"=== placeMark -- subAdministrativeArea: %@ ===",placeMark.subAdministrativeArea);
    // 地级市/直辖市，例如：北京市
    NSLog(@"=== placeMark -- locality: %@ ===",placeMark.locality);
    // 县/区，例如：海淀区
    NSLog(@"=== placeMark -- subLocality: %@ ===",placeMark.subLocality);
    // 街道名称，例如：中关村大街甲1号
    NSLog(@"=== placeMark -- thoroughfare: %@ ===",placeMark.thoroughfare);
    // 街道附加信息，例如门牌号等
    NSLog(@"=== placeMark -- subThoroughfare: %@ ===",placeMark.subThoroughfare);
    NSLog(@"=== placeMark -- region: %@ ===",placeMark.region);
    // 湖泊/水源名称
    NSLog(@"=== placeMark -- inlandWater: %@ ===",placeMark.inlandWater);
    // 大洋名称
    NSLog(@"=== placeMark -- ocean: %@ ===",placeMark.ocean);
    // 周边景点集合
    NSLog(@"=== placeMark -- areasOfInterest: %@ ===",placeMark.areasOfInterest);
      
    if (@available(iOS 11.0, *)) {
        NSLog(@"=== placeMark -- postalAddress: %@ ===",placeMark.postalAddress);
    } else  if (@available(iOS 9.0, *)) {
        // Fallback on earlier versions
        NSLog(@"=== placeMark -- timeZone: %@ ===",placeMark.timeZone);
    }
    
    [placeMark.areasOfInterest enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"=== 周边景点 :%@ ===",obj);
    }];
   
    self->_address = [NSString stringWithFormat:@"%@ %@ %@",placeMark.locality,placeMark.subLocality,placeMark.thoroughfare];
    NSLog(@"=== address :%@===",self->_address);
}

#pragma mark - 获取当前地理位置

- (CLLocation *)currentLocation {
    return self.location.location;
}

#pragma mark - CLLocationManagerDelegate

///////////////
// start AuthorizationStatus
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
   
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
            break;
        case kCLAuthorizationStatusDenied:
             [self stopLocation];
            break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
            if (_statusBlock) {
                _statusBlock();
            }
            [manager startUpdatingLocation];
            break;
        case kCLAuthorizationStatusAuthorizedAlways:
            break;
        default:
            break;
    }
    NSLog(@"=== status : %d === ",status);
}
// end AuthorizationStatus

//////////////////
// start update location
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    NSLog(@"=== didUpdateLocations ===");
    if (_locationBlock) {
        _locationBlock(locations,self);
    }
    if (_needReverseGeocode) {
        [self localtionAddress];
    }
    [self stopLocation];
}

- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager {
    NSLog(@"=== locationManagerDidPauseLocationUpdates ===");
}

- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager {
    NSLog(@"=== locationManagerDidResumeLocationUpdates ===");
    if (_needReverseGeocode){
        [self localtionAddress];
    }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"=== didFailWithError ===");
    if (_errorBlock) {
        _errorBlock(error);
    }
}

// end update location


////////////////
// start region
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
   // [manager requestStateForRegion:region];
    NSLog(@"=== didEnterRegion ===");
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
   // [manager requestStateForRegion:region];
    NSLog(@"=== didExitRegion ===");
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    NSLog(@"=== didStartMonitoringForRegion ===");
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
    NSLog(@"=== didDetermineState ===");
    switch (state) {
        case CLRegionStateInside:
            NSLog(@"=== 在范围内 ===");
            break;
        case CLRegionStateOutside:
            NSLog(@"=== 在范围外 ===");
            break;
        default:
            break;
    }
}

- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
    NSLog(@"=== monitoringDidFailForRegion ===");
    if (_errorBlock){
        _errorBlock(error);
    }
}

// end region


- (void)geocoderFromDictionary:(NSDictionary *)addressDic {
    NSParameterAssert(addressDic);
    LOCK(_lock)
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_11_0
    CNMutablePostalAddress *postalAddress = [CNMutablePostalAddress new];
    postalAddress.street = addressDic[@"street"];
    postalAddress.subLocality = addressDic[@"subLocality"];
    postalAddress.city = addressDic[@"city"];
    postalAddress.subAdministrativeArea = addressDic[@"subAdministrativeArea"];
    postalAddress.state = addressDic[@"state"];
    postalAddress.postalCode = addressDic[@"postalCode"];
    postalAddress.country = addressDic[@"country"];
    postalAddress.ISOCountryCode = addressDic[@"ISOCountryCode"];
    
    UNLOCK(_lock)
    [self.localtionGeocoder geocodePostalAddress:postalAddress completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        [placemarks enumerateObjectsUsingBlock:^(CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [self parsePlaceMark:obj];
        }];
    }];
#else
    [self.localtionGeocoder geocodeAddressDictionary:addressDic completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        [placemarks enumerateObjectsUsingBlock:^(CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [self parsePlaceMark:obj];
        }];
    }];
    
#endif
}

- (void)geocoderFromAddString:(NSString *)address {
    NSParameterAssert(address);
    [self.localtionGeocoder geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        [placemarks enumerateObjectsUsingBlock:^(CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [self parsePlaceMark:obj];
        }];
    }];
}

@end

